package com.dg.river.netty.axle.net;



import com.dg.river.netty.axle.msg2dev.BaseMsg;
import com.dg.river.netty.axle.msg2dev.DevMsg;
import com.fasterxml.jackson.databind.ObjectMapper;

import org.msgpack.jackson.dataformat.JsonArrayFormat;
import org.msgpack.jackson.dataformat.MessagePackFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import io.netty.util.ReferenceCountUtil;

@ChannelHandler.Sharable
public class DeviceMsgEncoder  extends MessageToByteEncoder<DevMsg> {

    protected Logger logger = LoggerFactory.getLogger(getClass());

    @Override
    protected void encode(ChannelHandlerContext ctx, DevMsg devMsg, ByteBuf out) throws Exception {
        logger.debug(devMsg.toString());
        //打包报文头
        out.writeByte(devMsg.getHeader().getMsgFlag());
        out.writeByte(devMsg.getHeader().getVersion());
        //暂时写入长度为0
        out.writeInt(0);
        out.writeInt((int) devMsg.getHeader().getDeviceId());
        out.writeByte(devMsg.getHeader().getMsgType());
        out.writeByte(devMsg.getHeader().getMsgId());
        out.writeInt((int) (devMsg.getHeader().getTimestamp().getTime() / 1000));
        int nMsgLen = 0;
        //写入数据
        //messagepack打包数据
        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
        objectMapper.setAnnotationIntrospector(new JsonArrayFormat());
        byte[] msgbody = new byte[0];
        try {
            ((BaseMsg)devMsg.getBody()).beforePack();
            msgbody = objectMapper.writeValueAsBytes(devMsg.getBody());
        } catch (Exception e) {
            logger.error("msgPack打包出错", e);
            logger.error("无法打包{}", devMsg.getHeader().getMsgType());
            ctx.close();
            return;
        } finally {
            ReferenceCountUtil.release(devMsg);
        }
        out.writeBytes(msgbody);
        nMsgLen = msgbody.length;
        if (nMsgLen <= 0){
            logger.error("无法打包{}", devMsg.getHeader().getMsgType());
            //打包数据出错
            ctx.close();
            return;
        }
        //计算CRC校验码
        int crc = CRC16.CRC16(out, 6, nMsgLen+10);
        //比较CRC码
        out.writeShort(crc);
        //写入长度
        out.setInt(2, nMsgLen + 12);
    }
}
